{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 自编码器 (Autoencoders)\n",
    "## 7.1 基本概念\n",
    "自编码器（Autoencoder）是一种无监督的神经网络模型，它试图学习输入数据的压缩表示，并能够使用这种表示重构原始输入。自编码器由两部分组成：编码器（Encoder）和解码器（Decoder）。编码器将输入数据压缩成一个隐藏表示，解码器则将隐藏表示恢复成原始数据。\n",
    "## 7.2 关键技术\n",
    "自编码器的关键技术包括编码器和解码器。<br/>\n",
    "![Autoencoders](../images/7-Autoencoders-network.webp)<br/>\n",
    "编码器：编码器是自编码器的前半部分，它将输入数据压缩成一个隐藏表示。编码器可以是任何类型的模型，但最常见的是使用全连接网络或卷积神经网络。\n",
    "解码器：解码器是自编码器的后半部分，它将隐藏表示恢复成原始数据。解码器的结构通常与编码器相对称。\n",
    "自编码器的训练目标是最小化重构误差，即原始输入和重构输出之间的差异。这可以用以下数学公式表示：<br/>\n",
    "![Autoencoders](../images/7-Autoencoders-math.webp)<br/>\n",
    "其中， 是原始输入， f( ) 是编码器， g( ( )) 是解码器， 是损失函数，如均方误差。\n",
    "## 7.3 应用领域\n",
    "自编码器可以用于降维、特征学习、生成模型等多种任务。例如，它可以用于图像去噪、图像生成、文本生成等。\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 7.4 优点\n",
    "自编码器的主要优点是能够学习输入数据的压缩表示，这使得它在处理高维数据时具有很高的效率。此外，由于自编码器是无监督的，因此它不需要标签数据就可以进行训练。\n",
    "## 7.5 缺点\n",
    "自编码器的主要缺点是可能会遇到过拟合问题，特别是当网络容量过大或训练数据过少时。此外，自编码器学习的表示可能不如一些有监督的方法（如深度神经网络）那么好。\n",
    "## 7.6 实例分析\n",
    "变分自编码器（VAE）和生成对抗网络（GAN）是两种基于自编码器的生成模型，它们在图像生成等任务上取得了显著的成果。\n",
    "## 7.7 手动实现\n",
    "以下是一个简单的自编码器的 Python 实现："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 这段代码首先创建了一个编码器，然后创建了一个解码器，最后将编码器和解码器连接起来创建了一个自编码器。\n",
    "import keras\n",
    "from keras import layers\n",
    "\n",
    "# 创建编码器\n",
    "input_img = keras.Input(shape=(28, 28, 1))\n",
    "x = layers.Conv2D(16, (3, 3), activation='relu', padding='same')(input_img)\n",
    "x = layers.MaxPooling2D((2, 2), padding='same')(x)\n",
    "x = layers.Conv2D(8, (3, 3), activation='relu', padding='same')(x)\n",
    "x = layers.MaxPooling2D((2, 2), padding='same')(x)\n",
    "x = layers.Conv2D(8, (3, 3), activation='relu', padding='same')(x)\n",
    "encoded = layers.MaxPooling2D((2, 2), padding='same')(x)\n",
    "\n",
    "# 创建解码器\n",
    "x = layers.Conv2D(8, (3, 3), activation='relu', padding='same')(encoded)\n",
    "x = layers.UpSampling2D((2, 2))(x)\n",
    "x = layers.Conv2D(8, (3, 3), activation='relu', padding='same')(x)\n",
    "x = layers.UpSampling2D((2, 2))(x)\n",
    "x = layers.Conv2D(16, (3, 3), activation='relu')(x)\n",
    "x = layers.UpSampling2D((2, 2))(x)\n",
    "decoded = layers.Conv2D(1, (3, 3), activation='sigmoid', padding='same')(x)\n",
    "\n",
    "# 创建自编码器\n",
    "autoencoder = keras.Model(input_img, decoded)\n",
    "autoencoder.compile(optimizer='adam', loss='binary_crossentropy')"
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
